<template>
	<a-tree-select v-bind="getAttrs" @change="handleChange">
		<template #[item]="data" v-for="item in Object.keys($slots)">
			<slot :name="item" v-bind="data || {}"></slot>
		</template>
		<template #suffixIcon v-if="loading">
			<LoadingOutlined spin />
		</template>
	</a-tree-select>
</template>

<script lang="ts">
import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue';
import type { PropType } from 'vue';
import { TreeSelect } from 'ant-design-vue';
import { isArray, isFunction } from '@/utils/is';
import { get } from 'lodash-es';
import { LoadingOutlined } from '@ant-design/icons-vue';
export default defineComponent({
	name: 'ApiTreeSelect',
	components: { ATreeSelect: TreeSelect, LoadingOutlined },
	props: {
		api: { type: Function as PropType<(arg?: any) => Promise<Recordable>> },
		params: {
			type: [Object, Number, String] as PropType<Recordable | number | string>,
			default: '',
		},
		immediate: { type: Boolean, default: true },
		// 后他返回结果的key
		resultField: { type: String as PropType<string>, default: '' },
		fieldNames: { type: Object },
	},
	emits: ['options-change', 'change'],
	setup(props, { attrs, emit }) {
		const treeData = ref<Recordable[]>([]);
		const isFirstLoaded = ref<Boolean>(false);
		const loading = ref(false);
		const getAttrs = computed(() => {
			return {
				...(props.api ? { treeData: unref(treeData) } : {}),
				...attrs,
				fieldNames: props.fieldNames,
			};
		});

		function handleChange(...args: any[]) {
			emit('change', ...args);
		}

		watch(
			() => props.params,
			() => {
				!unref(isFirstLoaded) && fetch();
			},
			{ deep: true },
		);

		watch(
			() => props.immediate,
			v => {
				v && !isFirstLoaded.value && fetch();
			},
		);

		onMounted(() => {
			props.immediate && fetch();
		});

		async function fetch() {
			const { api } = props;
			if (!api || !isFunction(api)) return;
			loading.value = true;
			treeData.value = [];
			let result;
			try {
				result = await api(props.params);
			} catch (e) {
				console.error(e);
			}

			loading.value = false;
			if (!result) return;
			if (!isArray(result)) {
				result = get(result, props.resultField);
			}
			treeData.value = (result as Recordable[]) || [];
			isFirstLoaded.value = true;
			emit('options-change', treeData.value);
		}
		return { getAttrs, loading, handleChange };
	},
});
</script>
